import type { Metadata } from 'next'; import Link from 'next/link'; import { notFound, permanentRedirect } from 'next/navigation'; import { ExternalLink } from 'lucide-react'; import { PageHeader, Section, KV, Note } from '@/components/ui/section'; import { Badge } from '@/components/ui/badge'; import { EmptyState } from '@/components/ui/empty-state'; import { Freshness } from '@/components/ui/freshness'; import { Pager } from '@/components/ui/pager'; import { EvidenceTable } from '@/components/data/evidence-table'; import { GeneFrequencyTable } from '@/components/data/frequency-table'; import { getGeneBySymbol, variantsForGene, variantsForGeneCount, frequenciesForGene, VARIANT_PAGE_SIZE } from '@/lib/queries/genomics'; import { evidenceForGene, evidenceForGeneCount, evidenceCancersForGene, EVIDENCE_PAGE_SIZE } from '@/lib/queries/evidence'; import { loadProvenance } from '@/lib/queries/provenance'; import { recentPublicationsFor, recentPublicationsForCount, PUBLICATION_PAGE_SIZE } from '@/lib/queries/publications'; import { PublicationList } from '@/components/data/publication-list'; import { GraphLink } from '@/components/graph/graph-link'; import { fmtInt, humanize } from '@/lib/format'; import { pageInfo } from '@/lib/pagination'; import { int, withParams, type SP } from '@/lib/search-params'; export const revalidate = 3600; /** Cancer chips above the evidence table: the most-cited contexts only (every row still names its cancer). */ const CANCER_CHIPS = 20; export async function generateMetadata({ params }: { params: Promise<{ symbol: string }> }): Promise { const g = await getGeneBySymbol((await params).symbol); return g ? { title: `${g.symbol} โ€” gene`, description: `${g.symbol}${g.name ? ` (${g.name})` : ''}: curated cancer evidence, variants and cohort alteration frequencies.`, alternates: { canonical: `/gene/${g.symbol}` } } : { title: 'Gene' }; } export default async function GenePage({ params, searchParams }: { params: Promise<{ symbol: string }>; searchParams: Promise }) { const { symbol } = await params; const g = await getGeneBySymbol(symbol); if (!g) notFound(); if (g.symbol !== symbol) permanentRedirect(`/gene/${g.symbol}`); const sp = await searchParams; const evPageReq = int(sp, 'evPage', 1, 1, 100_000); const vPageReq = int(sp, 'vPage', 1, 1, 100_000); const cPageReq = int(sp, 'cPage', 1, 1, 100_000); const pPageReq = int(sp, 'pPage', 1, 1, 100_000); const [evTotal, vTotal, pTotal] = await Promise.all([evidenceForGeneCount(g.id, g.symbol), variantsForGeneCount(g.id), recentPublicationsForCount('gene', [g.id])]); const ev = pageInfo(evPageReq, EVIDENCE_PAGE_SIZE, evTotal); const vp = pageInfo(vPageReq, VARIANT_PAGE_SIZE, vTotal); const pp = pageInfo(pPageReq, PUBLICATION_PAGE_SIZE, pTotal); const [variants, evidence, freqs, pubs, cancersInEvidence] = await Promise.all([ vTotal ? variantsForGene(g.id, { page: vp.page, pageSize: vp.pageSize }) : Promise.resolve([]), evTotal ? evidenceForGene(g.id, g.symbol, { page: ev.page, pageSize: ev.pageSize }) : Promise.resolve([]), frequenciesForGene(g.id, g.symbol), pTotal ? recentPublicationsFor('gene', [g.id], { page: pp.page, pageSize: pp.pageSize }) : Promise.resolve([]), evTotal ? evidenceCancersForGene(g.id, g.symbol, CANCER_CHIPS) : Promise.resolve([]), ]); const prov = await loadProvenance([...evidence.map((e) => e.provenance_id), ...freqs.map((f) => f.provenance_id)]); const current = { evPage: ev.page > 1 ? ev.page : '', vPage: vp.page > 1 ? vp.page : '', pPage: pp.page > 1 ? pp.page : '', cPage: cPageReq > 1 ? cPageReq : '' }; const href = (o: Record, hash: string) => `/gene/${g.symbol}${withParams(current, o)}#${hash}`; return (
{g.symbol}} lede={g.name ?? undefined}>

{g.id} {g.hgnc_id ? ( {g.hgnc_id} ) : null} {g.ensembl_gene_id ? ( {g.ensembl_gene_id} ) : null} {g.ncbi_gene_id ? ( NCBI {g.ncbi_gene_id} ) : null} {g.civic_gene_id ? ( CIViC ) : null} {g.is_cancer_gene ? Cancer gene : null} {g.status}

{g.description ? (

{g.description}

) : null}
{evTotal ? ( <> {cancersInEvidence.length ? ( ) : null} Showing {fmtInt(ev.from)}โ€“{fmtInt(ev.to)} of {fmtInt(evTotal)} evidence items } /> href({ evPage: p > 1 ? p : '' }, 'evidence')} label="Evidence pages" noun="evidence items" /> ) : ( No curated evidence item involves this gene yet. )}
{freqs.length ? href({ cPage: p > 1 ? p : '' }, 'frequencies')} /> : No cohort frequency recorded for this gene.}
{pubs.length ? ( <> Showing {fmtInt(pp.from)}โ€“{fmtInt(pp.to)} of {fmtInt(pTotal)} publications } /> href({ pPage: p > 1 ? p : '' }, 'publications')} label="Publication pages" noun="publications" /> ) : ( No publication linked to this gene yet. )}
); }